package com.xinqi.modules.prepare.courseware.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xinqi.common.base.dto.CommonFileDTO;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.utils.json.JSON;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.mybatis.utils.Queries;
import com.xinqi.common.security.utils.UserHelp;
import com.xinqi.modules.prepare.common.dto.data.PrepareCoursewareData;
import com.xinqi.modules.prepare.common.service.PrepareAuthService;
import com.xinqi.modules.prepare.courseware.convert.PrepareCoursewareConvert;
import com.xinqi.modules.prepare.courseware.domain.PrepareCoursewareEntity;
import com.xinqi.modules.prepare.courseware.domain.PrepareCoursewarePartEntity;
import com.xinqi.modules.prepare.courseware.dto.req.PrepareCoursewareCreateDTO;
import com.xinqi.modules.prepare.courseware.dto.req.PrepareCoursewareDeleteDTO;
import com.xinqi.modules.prepare.courseware.dto.req.PrepareCoursewareQueryDTO;
import com.xinqi.modules.prepare.courseware.dto.req.PrepareCoursewareUpdateDTO;
import com.xinqi.modules.prepare.courseware.dto.rsp.PrepareCoursewareResultDTO;
import com.xinqi.modules.prepare.courseware.manager.PrepareCoursewareManager;
import com.xinqi.modules.prepare.courseware.manager.PrepareCoursewarePartManager;
import com.xinqi.modules.prepare.courseware.service.PrepareCoursewarePartService;
import com.xinqi.modules.prepare.courseware.service.PrepareCoursewareService;
import com.xinqi.modules.prepare.folder.manager.PrepareFileFolderManager;
import com.xinqi.modules.prepare.prepare.enums.PrepareMemberPermissionEnum;
import com.xinqi.modules.prepare.prepare.enums.PrepareOperateTypeEnum;
import com.xinqi.modules.prepare.prepare.enums.PrepareSubOperateTypeEnum;
import com.xinqi.modules.prepare.prepare.manager.PrepareOperateLogManager;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 备课区互动课件服务层实现
 *
 * @author: system
 * @date: 2023/03/19
 */
@Validated
@Service("prepareCoursewareService")
@RequiredArgsConstructor
public class PrepareCoursewareServiceImpl implements PrepareCoursewareService {
    private final PrepareCoursewareConvert prepareCoursewareConvert;
    private final PrepareCoursewareManager prepareCoursewareManager;
    private final PrepareCoursewarePartManager prepareCoursewarePartManager;
    private final PrepareCoursewarePartService prepareCoursewarePartService;
    private final PrepareFileFolderManager prepareFileFolderManager;
    private final PrepareOperateLogManager prepareOperateLogManager;
    private final PrepareAuthService prepareAuthService;
    @Lazy
    private final CoursewareSliceService coursewareSliceService;

    /**
     * 分页查询 备课区互动课件数据
     */
    @Override
    @DS("slaver")
    public PageInfo<PrepareCoursewareResultDTO> page(Param pageable, PrepareCoursewareQueryDTO query) {
        IPage<PrepareCoursewareEntity> page = prepareCoursewareManager.page(Pages.page(pageable), wrapper(query));
        return Pages.convert(page, prepareCoursewareConvert::convert);
    }

    /**
     * 查询 备课区互动课件数据
     */
    @Override
    public List<PrepareCoursewareResultDTO> find(PrepareCoursewareQueryDTO query) {
        return prepareCoursewareManager.list(wrapper(query)).stream().map(prepareCoursewareConvert::convert).collect(Collectors.toList());
    }

    private LambdaQueryWrapper<PrepareCoursewareEntity> wrapper(PrepareCoursewareQueryDTO query) {
        LambdaQueryWrapper<PrepareCoursewareEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(PrepareCoursewareEntity::getId, v));
        Queries.accept(query.getPrepareId(), v -> wrapper.eq(PrepareCoursewareEntity::getPrepareId, v));
        return wrapper;
    }

    /**
     * 根据id查询 备课区互动课件数据
     */
    @Override
    public PrepareCoursewareResultDTO findById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return Optional.ofNullable(prepareCoursewareManager.findById(id)).map(prepareCoursewareConvert::convert).orElse(null);
    }

    @Override
    public PrepareCoursewareData find(Long id) {
        return prepareCoursewareConvert.convert(findById(id));
    }

    /**
     * 新增 备课区互动课件数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(@Valid PrepareCoursewareCreateDTO dto) {
        prepareAuthService.check(dto.getPrepareId(), PrepareMemberPermissionEnum.新建);
        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(dto.getFiles()), "课件不能为空");

        PrepareCoursewareEntity entity = prepareCoursewareConvert.create(dto);
        entity.setUserId(UserHelp.userId());
        prepareCoursewareManager.save(entity);
        // 创建备课区文件
        prepareFileFolderManager.insertFile(entity, entity.getPrepareId(), dto.getFolderId(), dto.getIsAutoGenerateName());
        prepareOperateLogManager.addFileOperateLog(entity, PrepareOperateTypeEnum.FILE_EDIT, PrepareSubOperateTypeEnum.ADD);

        //保存备课区切片
        coursewareSliceService.coursewareSlice(dto, entity.getId());

        return entity.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(@Valid PrepareCoursewareData data) {
        PrepareCoursewareEntity entity = prepareCoursewareConvert.create(data);
        entity.setId(null);
        entity.setPartNum(Optional.ofNullable(data.getPartList()).map(List::size).orElse(0));
        entity.setUserId(UserHelp.userId());

        //保存课件
        prepareCoursewareManager.save(entity);

        // 创建备课区文件
        prepareFileFolderManager.insertFile(entity, entity.getPrepareId(), data.getFolderId());

        //保存切片
        if (CollectionUtils.isNotEmpty(data.getPartList())) {
            prepareCoursewarePartService.insert(data.getPrepareId(), entity.getId(), data.getPartList());
        }
        return entity.getId();
    }

    /**
     * 根据id修改 备课区互动课件数据，只更新课件上的文件时，没有题目；而更新题目的时候课件上的文件没有变动
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(@Valid PrepareCoursewareUpdateDTO dto) {
        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(dto.getFiles()), "课件不能为空");
        PrepareCoursewareEntity old = Optional.ofNullable(prepareCoursewareManager.getById(dto.getId())).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("数据不存在"));
        prepareAuthService.check(old.getPrepareId(), PrepareMemberPermissionEnum.编辑);
        PrepareCoursewareEntity entity = prepareCoursewareConvert.update(dto);
        boolean b = prepareCoursewareManager.updateById(entity);
        if (b) {
            // 更新备课区文件
            PrepareCoursewareEntity newEntity = prepareCoursewareManager.getById(dto.getId());
            prepareFileFolderManager.updateFile(newEntity, newEntity.getPrepareId());
            prepareOperateLogManager.addFileOperateLog(newEntity, PrepareOperateTypeEnum.FILE_EDIT, PrepareSubOperateTypeEnum.EDIT);
        }

        //url有变动时更新切片
        if (!Objects.equals(dto.getFiles().get(0), prepareCoursewareConvert.convert(old).getFiles().get(0))) {
            updateCoursewareSlice(dto);
        }

        //更新题目,题目需要挂在切片上
        if (CollectionUtils.isNotEmpty(dto.getPartList())) {
            prepareCoursewarePartService.update(dto.getPartList());
        }

        return b;
    }

    /**
     * 根据id删除 备课区互动课件数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        PrepareCoursewareEntity entity = Optional.ofNullable(prepareCoursewareManager.getById(id)).orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("数据不存在"));
        prepareAuthService.check(entity.getPrepareId(), PrepareMemberPermissionEnum.删除);
        boolean b = prepareCoursewareManager.deleteById(entity);
        if (b) {
            // 删除备课区文件
            prepareFileFolderManager.deleteFile(entity, entity.getPrepareId());
        }

        //删除切片，不能删除切片，因为切片为物理删除，删除后无法恢复
//        prepareCoursewarePartManager.deleteByCoursewareId(id);

        return b;
    }

    /**
     * 根据id删除 备课区互动课件数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(PrepareCoursewareDeleteDTO dto) {
        return deleteById(dto.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveBatchSlice(PrepareCoursewareCreateDTO dto, Long courseWareId, List<String> ossFileList) {
        if (CollectionUtils.isNotEmpty(ossFileList)) {
            List<PrepareCoursewarePartEntity> partList = new ArrayList<>();

            for (int i = 0; i < ossFileList.size(); i++) {
                String url = ossFileList.get(i);
                PrepareCoursewarePartEntity part = new PrepareCoursewarePartEntity();
                part.setPrepareId(dto.getPrepareId());
                part.setCoursewareId(courseWareId);
                part.setFileType(String.valueOf(dto.getFiles().get(0).getType()));
                part.setPageNumber(i + 1);
                part.setName("第" + (i + 1) + "个切片");
                part.setTotalScore(BigDecimal.ZERO);
                part.setQuestionTypeTotal(0);
                part.setQuestionTotal(0);

                CommonFileDTO file = new CommonFileDTO();
                file.setOssFilename(part.getName());
                file.setFilename(part.getName());
                file.setType(Integer.valueOf(part.getFileType()));
                file.setUrl(url);
                file.setFileUrl(url);
                part.setFile(JSON.stringify(file));

                partList.add(part);
            }

            prepareCoursewarePartManager.saveBatch(partList);
        }
        return true;
    }

    /**
     * 更新切片，这里无法通过课件url知道是否更改了文件，所以全量更新
     *
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCoursewareSlice(PrepareCoursewareUpdateDTO dto) {
        List<PrepareCoursewarePartEntity> partList = prepareCoursewarePartManager.findByCoursewareId(dto.getId());
        prepareCoursewarePartManager.deletedByIds(partList.stream().map(PrepareCoursewarePartEntity::getId).collect(Collectors.toList()));
        coursewareSliceService.coursewareSlice(prepareCoursewareConvert.updateToCreate(dto), dto.getId());
    }

}
